package com.globallogic.javatrainings.sergiiivanov.controller;

import java.io.IOException;

import com.globallogic.javatrainings.sergiiivanov.model.Const;
import com.globallogic.javatrainings.sergiiivanov.model.University;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityException;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityFailure;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityWarning;
import com.globallogic.javatrainings.sergiiivanov.resources.Messages;
import com.globallogic.javatrainings.sergiiivanov.view.GUI;

/**
 * public static void main(String[] args)<br>
 * 
 * @author Sergey
 * 
 */
class Main {
    static DataReader dr = new DataReader();

    /**
     * Calls {@link #mainStart(String[])} <br>
     * then {@link #mainBody(University)} <br>
     * and finally {@link #mainSave(University)}
     * 
     * @param args
     */
    public static void main(String[] args) {
        UniversityException.debugEnabled = false;
        University university = mainStart(args);
        if (university != null) {
            mainBody(university);
            mainSave(university);
        }
        GUI.getGUI().show(Messages.BYE);
        GUI.getGUI().show(Messages.CREDITS);
    }

    /**
     * Keeps current controller starting from instance of
     * {@link BasicController}<br>
     * calls currentCoontroller.initiate(currentUniversity) in a loop intil
     * called controller return <b>null</b><br>
     * once <b>null</b> received - closes input streams and returns
     * 
     * @param university
     *            currently loaded {@link University}
     */
    static void mainBody(University university) {
        BasicController controller = new BasicController();
        while (controller != null) {
            try {
                controller = controller.initiate(university);
            } catch (UniversityFailure e) {
                GUI.getGUI().error("Some problem happened! Program will be closed now.", e.getMessage());
                break;
            }
        }
        InputController.close();
    }

    /**
     * Shows startup menu and asks for university to load<br>
     * Returns selected university
     * 
     * @param args
     */
    static University mainStart(String[] args) {
        GUI.getGUI().show(Messages.WELCOME);
        String fileName = readArgs(args);
        if (!Const.STRING_EMPTY.equals(fileName)) {
            dr.fileName = fileName;
            try {
                return dr.readData();
            } catch (Exception e) {
                GUI.getGUI().error("Failed to read file " + fileName, e.getLocalizedMessage());
            }
        }
        GUI.getGUI().show(Messages.WELCOME_MENU_HEAD);
        GUI.getGUI().showLineOfList(Messages.WELCOME_START_NEW, -1);
        GUI.getGUI().showLineOfList(Messages.WELCOME_USE_TEMPLATES, 0);
        GUI.getGUI().show(Messages.WELCOME_LOAD_FILE);
        String[] files = dr.getFilesList();
        GUI.getGUI().showArrayAsList(files, 1);
        GUI.getGUI().show(Messages.WELCOME_EXIT_OPTION);
        int startSelected = InputController.readInt();
        if (startSelected > 0 && startSelected <= files.length) {
            dr.fileName = files[startSelected - 1];
            try {
                return dr.readData();
            } catch (Exception e) {
                GUI.getGUI().show("Failed to load " + dr.fileName);
                startSelected = -1;
            }
        }
        if (startSelected == -1) {
            try {
                return new University(InputController.readString());
            } catch (UniversityWarning e1) {
                GUI.getGUI().error("Bad name for university", e1.getMessage());
                return null;
            }
        }
        if (startSelected == 0) {
            try {
                return UniversityTemplates.universityTemplte1();
            } catch (UniversityException e) {
                GUI.getGUI().error("Failed to load template", e.getMessage());
            }
        }
        ;
        return null;
    }

    /**
     * Saves university into file
     * 
     * @param university
     */
    static void mainSave(University university) {
        try {
            GUI.getGUI().show(Messages.SAVING_DATA + dr.getFileName());
            dr.saveDataToFile(university);
            GUI.getGUI().show("Data saved successfully");

        } catch (Exception e) {
            GUI.getGUI().error("Failed to save data", e.getMessage());
            GUI.getGUI().show(Messages.SORRY_BYE);
            e.printStackTrace();
        }
        InputController.closeMacro();
    }

    private final static String readArgs(String[] args) {
        String result = Const.STRING_EMPTY;
        for (String arg : args) {
            if (arg.startsWith("-file:")) {
                result = arg.replace("-file:", "");
            } else if (arg.startsWith("-macro:")) {
                try {
                    InputController.saveMacroEnabled(arg.replace("-macro:", ""));
                } catch (IOException e) {
                    GUI.getGUI().error("Failed to start macro", e.getLocalizedMessage());
                }
            } else if (arg.startsWith("-debug")) {
                UniversityException.debugEnabled = true;
            } else if (arg.startsWith("-brute")) {
                InputController.useBrute = false;
                GUI.getGUI().show("Brute option is disabled in this version");
            } else {
                GUI.getGUI().show("Help on University manager application\n" +
                        "run as University.jar [-file:savedfilename.usav] [-macro:newmacrofilename.txt] [-debug] [-?]\n" +
                        " -file:savedfilename.usav      loads saved university from provided file\n" +
                        " -macro:newmacrofilename.txt   saves all user input into given file \n" +
                        " -debug                        saves all errors into log.txt file\n" +
                        " -?                            shows this screen");
            }
        }
        return result;
    }

}
